개요
본 문서는 Timefit 예약 관리 시스템의 API 응답 및 에러 처리 규격을 정의합니다.
공통 Response 구조
성공 응답 (2xx)
json
{
"success": true,
"message": "처리 결과 메시지",
"data": {
// 실제 응답 데이터
}
}
실패 응답 (4xx, 5xx)
json
{
"success": false,
"message": "요청 처리 중 오류가 발생했습니다",
"error": {
"code": "ERROR_CODE",
"message": "상세 에러 메시지",
"field": "에러가 발생한 필드명" // 선택적
}
}
HTTP 상태 코드 정의
HTTP Status | 설명 | 사용 상황 |
---|---|---|
200 | OK | 요청 성공 (조회, 수정, 삭제) |
201 | Created | 리소스 생성 성공 (회원가입, 예약 생성) |
400 | Bad Request | 클라이언트 요청 오류 (비즈니스 로직 오류, 검증 실패) |
401 | Unauthorized | 인증 실패 (토큰 없음, 토큰 만료) |
403 | Forbidden | 권한 없음 (리소스 접근 권한 부족) |
404 | Not Found | 리소스 없음 |
409 | Conflict | 리소스 충돌 (중복 생성) |
500 | Internal Server Error | 서버 내부 오류 |
Error Code 정의
인증 관련
에러 코드 | Status | 상태 코드 | 메시지 | 설명 |
---|---|---|---|---|
EMAIL_ALREADY_EXISTS | 회원 중복 | 409 | "이미 존재하는 이메일입니다" | 회원가입 시 이메일 중복 |
BUSINESS_NUMBER_ALREADY_EXISTS | 사업자번호 중복 | 409 | "이미 등록된 사업자번호입니다" | 사업자번호 중복 |
INVALID_CREDENTIALS | 인증 실패 | 401 | "이메일 또는 비밀번호가 올바르지 않습니다" | 로그인 정보 불일치 |
USER_NOT_FOUND | 사용자 없음 | 404 | "사용자를 찾을 수 없습니다" | 존재하지 않는 사용자 |
TOKEN_EXPIRED | 토큰 만료 | 401 | "토큰이 만료되었습니다" | JWT 토큰 만료 |
TOKEN_INVALID | 토큰 무효 | 401 | "유효하지 않은 토큰입니다" | JWT 토큰 검증 실패 |
ACCESS_DENIED | 접근 거부 | 403 | "접근 권한이 없습니다" | 권한 부족 |
OAUTH_PROVIDER_ERROR | OAuth 오류 | 400 | "OAuth 인증 중 오류가 발생했습니다" | OAuth 로그인 실패 |
업체 관리 관련
에러 코드 | Status | 상태 코드 | 메시지 | 설명 |
---|---|---|---|---|
BUSINESS_NOT_FOUND | 업체 없음 | 404 | "업체 정보를 찾을 수 없습니다" | 존재하지 않는 업체 |
BUSINESS_ALREADY_EXISTS | 업체 중복 | 409 | "이미 등록된 업체가 있습니다" | 업체 중복 등록 |
BUSINESS_INFO_INCOMPLETE | 정보 미완성 | 400 | "업체 기본 정보가 완성되지 않았습니다" | 필수 정보 누락 |
BUSINESS_HOURS_INVALID | 영업시간 오류 | 400 | "영업시간 설정이 올바르지 않습니다" | 영업시간 설정 오류 |
AVAILABLE_SLOT_CONFLICT | 시간 충돌 | 409 | "예약 가능 시간이 중복됩니다" | 시간 슬롯 충돌 |
INSUFFICIENT_PERMISSION | 역할별 권한 부족 | |||
USER_NOT_BUSINESS_MEMBER | 업체 구성원 아님 |
예약 관련
에러 코드 | Status | 상태 코드 | 메시지 | 설명 |
---|---|---|---|---|
RESERVATION_NOT_FOUND | 예약 없음 | 404 | "예약 정보를 찾을 수 없습니다" | 존재하지 않는 예약 |
RESERVATION_SLOT_UNAVAILABLE | 예약 불가 | 400 | "선택한 시간대는 예약할 수 없습니다" | 예약 불가능한 시간 |
RESERVATION_ALREADY_EXISTS | 예약 중복 | 409 | "해당 시간대에 이미 예약이 있습니다" | 시간대 중복 예약 |
RESERVATION_CAPACITY_EXCEEDED | 인원 초과 | 400 | "예약 가능 인원을 초과했습니다" | 수용 인원 초과 |
RESERVATION_DEADLINE_PASSED | 기한 초과 | 400 | "예약 변경/취소 기한이 지났습니다" | 변경/취소 기한 초과 |
RESERVATION_INVALID_STATUS | 상태 오류 | 400 | "현재 예약 상태에서는 처리할 수 없습니다" | 잘못된 상태 변경 |
RESERVATION_PAST_DATE | 과거 날짜 | 400 | "과거 날짜는 예약할 수 없습니다" | 과거 날짜 예약 시도 |
INSUFFICIENT_PERMISSION | 역할별 권한 부족 | |||
NOT_BUSINESS_MEMBER | 업체 구성원 아님 | |||
NOT_RESERVATION_OWNER | 예약 소유권 없음 |
채팅 관련
에러 코드 | Status | 상태 코드 | 메시지 | 설명 |
---|---|---|---|---|
CHAT_ROOM_NOT_FOUND | 채팅방 없음 | 404 | "채팅방을 찾을 수 없습니다" | 존재하지 않는 채팅방 |
CHAT_ACCESS_DENIED | 채팅 접근 거부 | 403 | "채팅방에 접근할 권한이 없습니다" | 채팅방 접근 권한 없음 |
CHAT_MESSAGE_TOO_LONG | 메시지 길이 초과 | 400 | "메시지가 너무 깁니다 (최대 500자)" | 메시지 길이 제한 초과 |
CHAT_FILE_SIZE_EXCEEDED | 파일 크기 초과 | 400 | "첨부 파일 크기가 너무 큽니다 (최대 5MB)" | 첨부 파일 크기 제한 |
CHAT_FILE_TYPE_NOT_ALLOWED | 파일 형식 오류 | 400 | "지원하지 않는 파일 형식입니다" | 허용되지 않는 파일 형식 |
CHAT_ROOM_ALREADY_EXISTS | 채팅방 중복 | 409 | "이미 생성된 채팅방이 있습니다" | 채팅방 중복 생성 |
알림 관련
에러 코드 | Status | 상태 코드 | 메시지 | 설명 |
---|---|---|---|---|
NOTIFICATION_NOT_FOUND | 알림 없음 | 404 | "알림을 찾을 수 없습니다" | 존재하지 않는 알림 |
NOTIFICATION_ALREADY_READ | 알림 중복 읽음 | 400 | "이미 읽은 알림입니다" | 중복 읽음 처리 |
NOTIFICATION_SEND_FAILED | 알림 전송 실패 | 500 | "알림 전송에 실패했습니다" | 알림 전송 오류 |
고객 정보 관리 관련
에러 코드 | Status | 상태 코드 | 메시지 | 설명 |
---|---|---|---|---|
CUSTOMER_NOT_FOUND | 고객 없음 | 404 | "고객 정보를 찾을 수 없습니다" | 존재하지 않는 고객 |
CUSTOMER_NOTE_TOO_LONG | 메모 길이 초과 | 400 | "고객 메모가 너무 깁니다 (최대 1000자)" | 메모 길이 제한 초과 |
CUSTOMER_TAG_LIMIT_EXCEEDED | 태그 개수 초과 | 400 | "고객 태그는 최대 10개까지 가능합니다" | 태그 개수 제한 |
CUSTOMER_NOT_BUSINESS_CUSTOMER | ||||
다른 업체 고객 접근 시도 | ||||
PRIVATE_NOTE_ACCESS_DENIED | ||||
비공개 메모 접근 권한 부족 |
검증 관련
에러 코드 | Status | 상태 코드 | 메시지 | 설명 |
---|---|---|---|---|
VALIDATION_ERROR | 검증 오류 | 400 | "입력값이 올바르지 않습니다" | 일반적인 검증 실패 |
REQUIRED_FIELD_MISSING | 필수 필드 누락 | 400 | "필수 항목이 누락되었습니다" | 필수 필드 누락 |
INVALID_EMAIL_FORMAT | 이메일 형식 오류 | 400 | "이메일 형식이 올바르지 않습니다" | 이메일 형식 검증 실패 |
INVALID_PHONE_FORMAT | 전화번호 형식 오류 | 400 | "전화번호 형식이 올바르지 않습니다" | 전화번호 형식 검증 실패 |
INVALID_BUSINESS_NUMBER | 사업자번호 형식 오류 | 400 | "사업자번호 형식이 올바르지 않습니다" | 사업자번호 형식 검증 실패 |
PASSWORD_TOO_WEAK | 비밀번호 강도 부족 | 400 | "비밀번호가 너무 약합니다" | 비밀번호 복잡도 미달 |
INVALID_DATE_FORMAT | 날짜 형식 오류 | 400 | "날짜 형식이 올바르지 않습니다" | 날짜 형식 검증 실패 |
INVALID_TIME_FORMAT | 시간 형식 오류 | 400 | "시간 형식이 올바르지 않습니다" | 시간 형식 검증 실패 |
시스템 관련
에러 코드 | Status | 상태 코드 | 메시지 | 설명 |
---|---|---|---|---|
INTERNAL_SERVER_ERROR | 서버 오류 | 500 | "서버 내부 오류가 발생했습니다" | 일반적인 서버 오류 |
DATABASE_CONNECTION_ERROR | DB 연결 오류 | 500 | "데이터베이스 연결 오류가 발생했습니다" | DB 연결 실패 |
DATABASE_QUERY_ERROR | DB 쿼리 오류 | 500 | "데이터베이스 쿼리 실행 중 오류가 발생했습니다" | SQL 쿼리 실행 실패 |
DATABASE_TIMEOUT_ERROR | DB 타임아웃 | 500 | "데이터베이스 응답 시간이 초과되었습니다" | DB 응답 지연 |
REDIS_CONNECTION_ERROR | Redis 연결 오류 | 500 | "Redis 서버 연결 오류가 발생했습니다" | Redis 연결 실패 |
REDIS_OPERATION_ERROR | Redis 작업 오류 | 500 | "Redis 작업 처리 중 오류가 발생했습니다" | Redis 명령어 실행 실패 |
EXTERNAL_API_ERROR | 외부 API 오류 | 500 | "외부 API 호출 중 오류가 발생했습니다" | 외부 서비스 오류 |
FILE_UPLOAD_ERROR | 파일 업로드 오류 | 500 | "파일 업로드 중 오류가 발생했습니다" | 파일 업로드 실패 |
FILE_STORAGE_ERROR | 파일 저장 오류 | 500 | "파일 저장소 접근 중 오류가 발생했습니다" | 파일 시스템 오류 |
→ RDB, Inmemory 명확하게 나누고 싶다 생각해서 저렇게 했는데 다시 보니 아닌듯. 사례 찾아보고 맞춰 수정하기
페이지네이션 구조
일반 페이지네이션 응답
json
{
"success": true,
"message": "조회가 완료되었습니다",
"data": {
"content": [
// 실제 데이터 배열
],
"pagination": {
"page": 1,
"size": 10,
"totalElements": 25,
"totalPages": 3,
"hasNext": true,
"hasPrevious": false
}
}
}
무한 스크롤 (Cursor-based) 응답
json
{
"success": true,
"message": "조회가 완료되었습니다",
"data": {
"content": [
// 실제 데이터 배열
],
"cursor": {
"hasNext": true,
"nextCursor": "eyJpZCI6MTIzLCJjcmVhdGVkQXQi...",
"size": 20
}
}
}
페이지네이션 Query Parameters
파라미터 | 타입 | 기본값 | 설명 | 제약 |
---|---|---|---|---|
page | integer | 1 | 페이지 번호 (1부터 시작) | 최소 1 |
size | integer | 10 | 페이지 크기 | 최소 1, 최대 100 |
sort | string | null | 정렬 기준 | "field,direction" 형식 |
cursor | string | null | 무한 스크롤용 커서 | Base64 인코딩된 문자열 |
정렬 옵션 예시
createdAt,desc
: 생성일 내림차순name,asc
: 이름 오름차순reservationTime,desc
: 예약시간 내림차순
인증 헤더
Bearer Token 사용
Authorization: Bearer {accessToken}
JWT 토큰 구조
json
{
"header": {
"typ": "JWT",
"alg": "HS256"
},
"payload": {
"sub": "550e8400-e29b-41d4-a716-446655440000",
"email": "business@example.com",
"role": "BUSINESS",
"iat": 1640995200,
"exp": 1641081600
}
}
토큰 갱신
POST /api/auth/refresh
Content-Type: application/json
{
"refreshToken": "your-refresh-token"
}
공통 필터링 Parameters
날짜 범위 필터링
파라미터 | 타입 | 설명 | 형식 |
---|---|---|---|
startDate | string | 시작 날짜 | YYYY-MM-DD |
endDate | string | 종료 날짜 | YYYY-MM-DD |
상태 필터링 (예약)
값 | 설명 |
---|---|
PENDING | 대기 중 |
CONFIRMED | 확정됨 |
COMPLETED | 완료됨 |
CANCELLED | 취소됨 |
NO_SHOW | 노쇼 |
검색 Parameters
파라미터 | 타입 | 설명 |
---|---|---|
keyword | string | 검색 키워드 |
searchType | string | 검색 유형 (name, email, phone 등) |